home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / symb_lib / symbpoly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-01  |  13.4 KB  |  293 lines

  1. /******************************************************************************
  2. * SymbPoly.c - Generic Curve/Surface to polygon/polylines conversion routines.*
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include "symb_loc.h"
  8. #include "dist_pts.h"
  9.  
  10. #define CURVE_PTS_DIST_RESOLUTION 10
  11.  
  12. static CagdCrvStruct
  13.     *GlblDeriv1MagSqrCrv = NULL,
  14.     *GlblCrvtrCrv = NULL;
  15. static CagdRType GlblCrvtrCrvTMin, GlblCrvtrCrvTMax;
  16.  
  17. static CagdPolylineStruct *SymbCrv2OptimalPolyline(CagdCrvStruct *Crv,
  18.                            int SamplesPerCurve);
  19. static RealType CrvCurvatureEvalFunc(RealType t);
  20.  
  21. /*****************************************************************************
  22. * DESCRIPTION:                                                               M
  23. * Routine to convert a single surface to set of triangles approximating it.  M
  24. *   FineNess is a finess control on result and the larger it is more         M
  25. * triangles may result.                                 M
  26. *   A value of 10 is a good starting value.                     M
  27. * NULL is returned in case of an error, otherwise list of CagdPolygonStruct. M
  28. *                                                                            *
  29. * PARAMETERS:                                                                M
  30. *   Srf:              To approximate into triangles.                         M
  31. *   FineNess:         Control on accuracy, the higher the finer.             M
  32. *   ComputeNormals:   If TRUE, normal information is also computed.          M
  33. *   FourPerFlat:      If TRUE, four triangles are created per flat surface.  M
  34. *                     If FALSE, only 2 triangles are created.                M
  35. *   ComputeUV:        If TRUE, UV values are stored and returned as well.    M
  36. *                                                                            *
  37. * RETURN VALUE:                                                              M
  38. *   CagdPolygonStruct *:   A list of polygons with optional normal and/or    M
  39. *                         UV parametric information.                         M
  40. *                         NULL is returned in case of an error.              M
  41. *                                                                            *
  42. * KEYWORDS:                                                                  M
  43. *   SymbSrf2Polygons, polygonization, surface approximation                  M
  44. *****************************************************************************/
  45. CagdPolygonStruct *SymbSrf2Polygons(CagdSrfStruct *Srf,
  46.                     int FineNess,
  47.                     CagdBType ComputeNormals,
  48.                     CagdBType FourPerFlat,
  49.                     CagdBType ComputeUV)
  50. {
  51.     /* Make sure we do not deal with constant surfaces. */
  52.     if (Srf -> UOrder < 2 || Srf -> VOrder < 2) {
  53.         SYMB_FATAL_ERROR(SYMB_ERR_POLY_CONST_SRF);
  54.     return NULL;
  55.     }
  56.  
  57.  
  58.     switch (Srf -> GType) {
  59.     case CAGD_SBEZIER_TYPE:
  60.         return BzrSrf2Polygons(Srf, FineNess, ComputeNormals, FourPerFlat,
  61.                                    ComputeUV);
  62.     case CAGD_SBSPLINE_TYPE:
  63.         return BspSrf2Polygons(Srf, FineNess, ComputeNormals, FourPerFlat,
  64.                                    ComputeUV);
  65.     case CAGD_SPOWER_TYPE:
  66.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  67.         return NULL;
  68.     default:
  69.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_SRF);
  70.         return NULL;
  71.     }
  72. }
  73.  
  74. /*****************************************************************************
  75. * DESCRIPTION:                                                               M
  76. *   Routine to convert a single surface to NumOfIsolines polylines in each   M
  77. * parametric direction with SamplesPerCurve in each isoparametric curve.     M
  78. *   Polyline are always E3 of CagdPolylineStruct type.                 M
  79. *   NULL is returned in case of an error, otherwise list of                  M
  80. * CagdPolylineStruct. Attempt is made to extract isolines along C1           M
  81. * discontinuities first.                             M
  82. *                                                                            *
  83. * PARAMETERS:                                                                M
  84. *   Srf:                 Srf to extract isoparametric curves from.           M
  85. *   NumOfIsocurves:      To extarct from Srf in each (U or V) direction.     M
  86. *   SamplesPerCurve:     Fineness control on piecewise linear curve          M
  87. *                        approximation.                                      M
  88. *   Optimal:         Use optimal approximation of isocurves.         M
  89. *                                                                            *
  90. * RETURN VALUE:                                                              M
  91. *   CagdPolylineStruct *: List of polylines representing a piecewise linear  M
  92. *                         approximation of the extracted isoparamteric       M
  93. *                         curves or NULL is case of an error.                M
  94. *                                                                            *
  95. * KEYWORDS:                                                                  M
  96. *   SymbSrf2Polylines, polylines, isoparametric curves                       M
  97. *****************************************************************************/
  98. CagdPolylineStruct *SymbSrf2Polylines(CagdSrfStruct *Srf,
  99.                       int NumOfIsocurves[2],
  100.                       int SamplesPerCurve,
  101.                       int Optimal)
  102. {
  103.     if (Optimal) {
  104.     CagdCrvStruct *Crv,
  105.         *Crvs = SymbSrf2Curves(Srf, NumOfIsocurves);
  106.     CagdPolylineStruct *Poly,
  107.         *Polys = NULL;
  108.  
  109.     for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) {
  110.         Poly = SymbCrv2OptimalPolyline(Crv, SamplesPerCurve);
  111.         Poly -> Pnext = Polys;
  112.         Polys = Poly;
  113.     }
  114.  
  115.     CagdCrvFreeList(Crvs);
  116.     return Polys;    
  117.     }
  118.     
  119.  
  120.     switch (Srf -> GType) {
  121.     case CAGD_SBEZIER_TYPE:
  122.         return BzrSrf2Polylines(Srf, NumOfIsocurves, SamplesPerCurve);
  123.     case CAGD_SBSPLINE_TYPE:
  124.         return BspSrf2Polylines(Srf, NumOfIsocurves, SamplesPerCurve);
  125.     case CAGD_SPOWER_TYPE:
  126.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  127.         return NULL;
  128.     default:
  129.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_SRF);
  130.         return NULL;
  131.     }
  132. }
  133.  
  134. /*****************************************************************************
  135. * DESCRIPTION:                                                               M
  136. *   Routine to extract from a surface NumOfIsoline isocurve list         M
  137. * in each param. direction.                             M
  138. *   Iso parametric curves are sampled equally spaced in parametric space.    M
  139. *   NULL is returned in case of an error, otherwise list of CagdCrvStruct.   M
  140. *                                                                            *
  141. * PARAMETERS:                                                                M
  142. *   Srf:             To extract isoparametric curves from.                   M
  143. *   NumOfIsocurves:  In each (U or V) direction.                             M
  144. *                                                                            *
  145. * RETURN VALUE:                                                              M
  146. *   CagdCrvStruct *:  List of extracted isoparametric curves. These curves   M
  147. *                     inherit the order and continuity of the original Srf.  M
  148. *                     NULL is returned in case of an error.                  M
  149. *                                                                            *
  150. * KEYWORDS:                                                                  M
  151. *   SymbSrf2Curves, curves, isoparametric curves                             M
  152. *****************************************************************************/
  153. CagdCrvStruct *SymbSrf2Curves(CagdSrfStruct *Srf, int NumOfIsocurves[2])
  154. {
  155.     switch (Srf -> GType) {
  156.     case CAGD_SBEZIER_TYPE:
  157.         return BzrSrf2Curves(Srf, NumOfIsocurves);
  158.     case CAGD_SBSPLINE_TYPE:
  159.         return BspSrf2Curves(Srf, NumOfIsocurves);
  160.     case CAGD_SPOWER_TYPE:
  161.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  162.         return NULL;
  163.     default:
  164.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_SRF);
  165.         return NULL;
  166.     }
  167. }
  168.  
  169. /*****************************************************************************
  170. * DESCRIPTION:                                                               M
  171. *   Routine to approx. a single curve as a polyline with SamplesPerCurve     M
  172. * samples. Polyline is always E3 CagdPolylineStruct type.             M
  173. *   NULL is returned in case of an error, otherwise CagdPolylineStruct.         M
  174. *                                                                            *
  175. * PARAMETERS:                                                                M
  176. *   Crv:              To approximate as a polyline.                          M
  177. *   SamplesPerCurve:  Number of samples to approximate with.                 M
  178. *   Optimal:          If TRUE, yse optimal approximation of isocurves.         M
  179. *                     Otherwise, the curve is sampled using equally spaced   M
  180. *              samples in parametric space.                 M
  181. *   OptiLin:          If TRUE, optimize linear curves.                 M
  182. *                                                                            *
  183. * RETURN VALUE:                                                              M
  184. *   CagdPolylineStruct *:  A polyline representing the piecewise linear      M
  185. *                          approximation from, or NULL in case of an error.  M
  186. *                                                                            *
  187. * KEYWORDS:                                                                  M
  188. *   SymbCrv2Polyline, piecewise linear approximation, polyline               M
  189. *****************************************************************************/
  190. CagdPolylineStruct *SymbCrv2Polyline(CagdCrvStruct *Crv,
  191.                      int SamplesPerCurve,
  192.                      CagdBType Optimal,
  193.                      CagdBType OptiLin)
  194. {
  195.     if (Optimal)
  196.     return SymbCrv2OptimalPolyline(Crv, SamplesPerCurve);
  197.  
  198.     switch (Crv -> GType) {
  199.     case CAGD_CBEZIER_TYPE:
  200.         return BzrCrv2Polyline(Crv, SamplesPerCurve);
  201.     case CAGD_CBSPLINE_TYPE:
  202.         return BspCrv2Polyline(Crv, SamplesPerCurve, NULL, OptiLin);
  203.     case CAGD_CPOWER_TYPE:
  204.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  205.         return NULL;
  206.     default:
  207.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  208.         return NULL;
  209.     }
  210. }
  211.  
  212. /*****************************************************************************
  213. * DESCRIPTION:                                                               *
  214. * Routine to convert a single curve to polyline with SamplesPerCurve         *
  215. * samples.                                     *
  216. *   Polyline is always E3 of CagdPolylineStruct type.                  *
  217. *   Curve is sampled at optimal locations as to minimize the L-infinity         *
  218. * error between the curve and its polyline approximation.             *
  219. *   NULL is returned in case of an error, otherwise CagdPolylineStruct.         *
  220. *                                                                            *
  221. * PARAMETERS:                                                                *
  222. *   Crv:                To approiximate as a polyline.                       *
  223. *   SamplesPerCurve:    Number of samples one can take off the curve.        *
  224. *                                                                            *
  225. * RETURN VALUE:                                                              *
  226. *   CagdPolylineStruct *:   A polyline with SamplesPerCurve samples that     *
  227. *                           approixmates Crv.                                *
  228. *****************************************************************************/
  229. static CagdPolylineStruct *SymbCrv2OptimalPolyline(CagdCrvStruct *Crv,
  230.                            int SamplesPerCurve)
  231. {
  232.     int i;
  233.     CagdRType *TVals;
  234.     CagdPolylineStruct
  235.     *P = CagdPolylineNew(SamplesPerCurve);
  236.     CagdCrvStruct *CTmp;
  237.     CagdPolylnStruct
  238.     *NewPolyline = P -> Polyline;
  239.  
  240.     GlblCrvtrCrv = SymbCrv3DCurvatureSqr(Crv);
  241.     CTmp = CagdCrvDerive(Crv);
  242.     GlblDeriv1MagSqrCrv = SymbCrvDotProd(CTmp, CTmp);
  243.     CagdCrvDomain(Crv, &GlblCrvtrCrvTMin, &GlblCrvtrCrvTMax);
  244.  
  245.     TVals = DistPoint1DWithEnergy(SamplesPerCurve,
  246.                   GlblCrvtrCrvTMin, GlblCrvtrCrvTMax,
  247.                   CURVE_PTS_DIST_RESOLUTION,
  248.                   CrvCurvatureEvalFunc);
  249.  
  250.     for (i = 0; i < SamplesPerCurve; i++) {      /* Convert to E3 polyline. */
  251.     RealType
  252.         *R = CagdCrvEval(Crv, TVals[i]);
  253.  
  254.     CagdCoerceToE3(NewPolyline[i].Pt, &R, -1, Crv -> PType);
  255.     }
  256.  
  257.     CagdCrvFree(GlblCrvtrCrv);
  258.     CagdCrvFree(GlblDeriv1MagSqrCrv);
  259.     IritFree((VoidPtr) TVals);
  260.  
  261.     return P;
  262. }
  263.  
  264. /*****************************************************************************
  265. * DESCRIPTION:                                                               *
  266. * Evaluation function of curvature square. This function should return the   *
  267. * square root of the curvature, scaled by the arclength using GlblCrvtrCrv   *
  268. * GlblDeriv1MagSqrCrv that contain curvature square and arclength sqaure.    *
  269. *                                                                            *
  270. * PARAMETERS:                                                                *
  271. *   t:          Parameter at which to evalate the global curvature field.    *
  272. *                                                                            *
  273. * RETURN VALUE:                                                              *
  274. *   RealType:    Rstimated curvature square.                                 *
  275. *****************************************************************************/
  276. static RealType CrvCurvatureEvalFunc(RealType t)
  277. {
  278.     CagdRType CrvtrSqr, MagSqr, *R;
  279.  
  280.     if (t < GlblCrvtrCrvTMin)
  281.     t = GlblCrvtrCrvTMin;
  282.     if (t > GlblCrvtrCrvTMax)
  283.     t = GlblCrvtrCrvTMax;
  284.  
  285.     R = CagdCrvEval(GlblCrvtrCrv, t);
  286.     CrvtrSqr = fabs( R[1] / R[0] );
  287.     R = CagdCrvEval(GlblDeriv1MagSqrCrv, t);
  288.     MagSqr = GlblDeriv1MagSqrCrv -> PType == CAGD_PT_E1_TYPE ? R[1]
  289.                                  : R[1] / R[0];
  290.  
  291.     return sqrt( sqrt( CrvtrSqr ) * MagSqr );
  292. }
  293.